package service

import (
	"context"
	"fmt"
	"sync"
	"time"

	"sysu-giep/internal/config"
	"sysu-giep/internal/database/models"
	"sysu-giep/pkg/logger"

	"go.uber.org/zap"
	"gorm.io/gorm"
)

// BackUpService 备份服务
type BackUpService struct {
	cfg        *config.Config
	db         *gorm.DB
	tasks      map[string]*ScheduledTask
	tasksMutex sync.RWMutex
	ctx        context.Context
	cancel     context.CancelFunc
}

// ScheduledTask 定时任务
type ScheduledTask struct {
	ID          string
	Name        string
	Description string
	Schedule    time.Duration
	LastRun     time.Time
	NextRun     time.Time
	IsRunning   bool
	Handler     func() error
	Enabled     bool
}

// NewBackUpService 创建备份服务实例
func NewBackUpService(cfg *config.Config, db *gorm.DB) *BackUpService {
	ctx, cancel := context.WithCancel(context.Background())
	return &BackUpService{
		cfg:    cfg,
		db:     db,
		tasks:  make(map[string]*ScheduledTask),
		ctx:    ctx,
		cancel: cancel,
	}
}

// AddTask 添加定时任务
func (s *BackUpService) AddTask(task *ScheduledTask) {
	s.tasksMutex.Lock()
	defer s.tasksMutex.Unlock()

	task.NextRun = time.Now().Add(task.Schedule)
	s.tasks[task.ID] = task

	logger.Info("添加定时任务",
		zap.String("task_id", task.ID),
		zap.String("task_name", task.Name),
		zap.Duration("schedule", task.Schedule))
}

// RemoveTask 移除定时任务
func (s *BackUpService) RemoveTask(taskID string) {
	s.tasksMutex.Lock()
	defer s.tasksMutex.Unlock()

	if task, exists := s.tasks[taskID]; exists {
		task.Enabled = false
		delete(s.tasks, taskID)
		logger.Info("移除定时任务", zap.String("task_id", taskID))
	}
}

// Start 启动定时任务服务
func (s *BackUpService) Start() {
	logger.Info("启动定时任务服务")

	// 启动任务调度器
	go s.scheduler()

	// 启动任务执行器
	go s.executor()
}

// Stop 停止定时任务服务
func (s *BackUpService) Stop() {
	logger.Info("停止定时任务服务")
	s.cancel()
}

// scheduler 任务调度器
func (s *BackUpService) scheduler() {
	ticker := time.NewTicker(time.Minute) // 每分钟检查一次
	defer ticker.Stop()

	for {
		select {
		case <-s.ctx.Done():
			return
		case <-ticker.C:
			s.checkAndScheduleTasks()
		}
	}
}

// executor 任务执行器
func (s *BackUpService) executor() {
	for {
		select {
		case <-s.ctx.Done():
			return
		default:
			s.executeReadyTasks()
			time.Sleep(time.Second * 10) // 每10秒检查一次
		}
	}
}

// checkAndScheduleTasks 检查并调度任务
func (s *BackUpService) checkAndScheduleTasks() {
	s.tasksMutex.RLock()
	defer s.tasksMutex.RUnlock()

	now := time.Now()
	for _, task := range s.tasks {
		if task.Enabled && !task.IsRunning && now.After(task.NextRun) {
			logger.Info("任务准备执行",
				zap.String("task_id", task.ID),
				zap.String("task_name", task.Name))
		}
	}
}

// executeReadyTasks 执行就绪的任务
func (s *BackUpService) executeReadyTasks() {
	s.tasksMutex.Lock()
	defer s.tasksMutex.Unlock()

	now := time.Now()
	for _, task := range s.tasks {
		if task.Enabled && !task.IsRunning && now.After(task.NextRun) {
			go s.executeTask(task)
		}
	}
}

// executeTask 执行单个任务
func (s *BackUpService) executeTask(task *ScheduledTask) {
	s.tasksMutex.Lock()
	task.IsRunning = true
	task.LastRun = time.Now()
	s.tasksMutex.Unlock()

	defer func() {
		s.tasksMutex.Lock()
		task.IsRunning = false
		task.NextRun = time.Now().Add(task.Schedule)
		s.tasksMutex.Unlock()
	}()

	logger.Info("开始执行任务",
		zap.String("task_id", task.ID),
		zap.String("task_name", task.Name))

	startTime := time.Now()
	err := task.Handler()
	duration := time.Since(startTime)

	if err != nil {
		logger.ErrorLog("任务执行失败",
			zap.String("task_id", task.ID),
			zap.String("task_name", task.Name),
			zap.Error(err),
			zap.Duration("duration", duration))
	} else {
		logger.Info("任务执行成功",
			zap.String("task_id", task.ID),
			zap.String("task_name", task.Name),
			zap.Duration("duration", duration))
	}
}

// GetTaskStatus 获取任务状态
func (s *BackUpService) GetTaskStatus() map[string]interface{} {
	s.tasksMutex.RLock()
	defer s.tasksMutex.RUnlock()

	status := make(map[string]interface{})
	for id, task := range s.tasks {
		status[id] = map[string]interface{}{
			"name":        task.Name,
			"description": task.Description,
			"enabled":     task.Enabled,
			"is_running":  task.IsRunning,
			"last_run":    task.LastRun,
			"next_run":    task.NextRun,
			"schedule":    task.Schedule.String(),
		}
	}
	return status
}

// 预定义的定时任务

// DailyDataCleanupTask 每日数据清理任务
func (s *BackUpService) DailyDataCleanupTask() error {
	logger.Info("开始执行每日数据清理任务")

	// 清理过期的通知
	result := s.db.Exec(`
		DELETE FROM notification 
		WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY)
	`)
	if result.Error != nil {
		return fmt.Errorf("清理过期通知失败: %w", result.Error)
	}

	// 清理过期的会话token（如果有相关表）
	// result = s.db.Exec(`
	//     DELETE FROM user_sessions
	//     WHERE expires_at < NOW()
	// `)

	logger.Info("每日数据清理任务完成",
		zap.Int64("清理通知数量", result.RowsAffected))

	return nil
}

// DailyStatisticsTask 每日统计任务
func (s *BackUpService) DailyStatisticsTask() error {
	logger.Info("开始执行每日统计任务")

	// 统计用户数量
	var userCount int64
	s.db.Model(&models.User{}).Count(&userCount)

	// 统计项目数量
	var projectCount int64
	s.db.Model(&models.Project{}).Count(&projectCount)

	// 统计申请数量
	var applicationCount int64
	s.db.Model(&models.Application{}).Count(&applicationCount)

	logger.Info("每日统计完成",
		zap.Int64("用户数量", userCount),
		zap.Int64("项目数量", projectCount),
		zap.Int64("申请数量", applicationCount))

	return nil
}

// DailyBackupTask 每日备份任务
func (s *BackUpService) DailyBackupTask() error {
	logger.Info("开始执行每日备份任务")

	// 这里可以添加数据库备份逻辑
	// 例如：导出关键数据到文件、发送到云存储等

	// 示例：备份用户数据
	var users []models.User
	if err := s.db.Find(&users).Error; err != nil {
		return fmt.Errorf("备份用户数据失败: %w", err)
	}

	logger.Info("每日备份任务完成",
		zap.Int("备份用户数量", len(users)))

	return nil
}

// InitializeDefaultTasks 初始化默认任务
func (s *BackUpService) InitializeDefaultTasks() {
	// 每日数据清理任务 - 每天凌晨2点执行
	s.AddTask(&ScheduledTask{
		ID:          "daily_cleanup",
		Name:        "每周数据清理",
		Description: "清理过期的通知和会话数据",
		Schedule:    24 * time.Hour * 7,
		Handler:     s.DailyDataCleanupTask,
		Enabled:     true,
	})

	// 每日统计任务 - 每天凌晨3点执行
	s.AddTask(&ScheduledTask{
		ID:          "daily_statistics",
		Name:        "每日统计",
		Description: "统计用户、项目、申请等数据",
		Schedule:    24 * time.Hour,
		Handler:     s.DailyStatisticsTask,
		Enabled:     true,
	})

	// 每日备份任务 - 每天凌晨4点执行
	s.AddTask(&ScheduledTask{
		ID:          "daily_backup",
		Name:        "每日备份",
		Description: "备份关键数据",
		Schedule:    24 * time.Hour,
		Handler:     s.DailyBackupTask,
		Enabled:     true,
	})

	logger.Info("初始化默认定时任务完成")
}

// 常量定义
const (
	RefreshTime = time.Hour * 24
)
